
#include <iostream>
#include <string>
#include <vector>

#include "bocat/common/lrucache.hpp"

using namespace	bocat::common;


/// LRUCache type for use in the unit tests
typedef LRUCache<std::string,std::string> lru_type;

/// Dumps the cache for debugging.
std::string dump( lru_type *L ) { 
    lru_type::Key_List _list( L->get_all_keys() );
    std::string ret("");
    for( lru_type::Key_List_Iter liter = _list.begin(); liter != _list.end(); liter++ ) { 
        ret.append( *liter );
        ret.append( ":" );
        ret.append( L->get( *liter, false ) );
        ret.append( "\n" );
    }   
    std::cout << "Dump--" << std::endl << ret << "----" << std::endl;
    return ret;
}


int	main()
{

	lru_type	lru(3);

	std::string	removed;

	removed = lru.put( "one", "1");
	if (removed.size() > 0) {
		std::cout << " remove data '" << removed << "' from LRU cache\n";
	}

	removed = lru.put( "two", "2");
	if (removed.size() > 0) {
		std::cout << " remove data '" << removed << "' from LRU cache\n";
	}

	removed = lru.put( "three", "3");
	if (removed.size() > 0) {
		std::cout << " remove data '" << removed << "' from LRU cache\n";
	}

	removed = lru.put( "four", "4");
	if (removed.size() > 0) {
		std::cout << " remove data '" << removed << "' from LRU cache\n";
	}

	removed = lru.put( "five", "5");
	if (removed.size() > 0) {
		std::cout << " remove data '" << removed << "' from LRU cache\n";
	}


	dump( &lru );

	std::cout << "fetch 'one' : " << lru.get( "one" ) << std::endl;
	std::cout << "fetch 'two' : " << lru.get( "two" ) << std::endl;
	std::cout << "fetch 'three' : " << lru.get( "three" ) << std::endl;
	std::cout << "fetch 'four' : " << lru.get( "four" ) << std::endl;

	{
		LRUCache< std::string, const char * >	ptr_cache(3);

		const char*	ptr_removed;
		std::string	key("one");
		ptr_removed = ptr_cache.put( key, key.c_str() );
		if (NULL != ptr_removed) {
			std::cout << " PTR put '" << key << "' return " << ptr_removed << std::endl;
		}

		key = "two";
		ptr_removed = ptr_cache.put( key, key.c_str() );
		if (NULL != ptr_removed) {
			std::cout << " PTR put '" << key << "' return " << ptr_removed << std::endl;
		}

		std::vector< std::string >	keys;
		keys.push_back( "one" );
		keys.push_back( "two" );
		keys.push_back( "three" );

		for (size_t i=0; i<keys.size(); i++) {
			const std::string&	key = keys[i];
			const char*	ptr_got = ptr_cache.get( key );

			if (ptr_got) {
				std::cout << " PTR fetch '" << key << "' : 0x" << static_cast< const void * >(ptr_got) << std::endl;
			}
			else {
				std::cout << " PTR fetch '" << key << "' : NULL " << std::endl;
				std::cout << " PTR fetch '" << key << "' : 0x" << static_cast< const void * >(ptr_got) << std::endl;
			}
		}
	}

	return	0;

}

